import { Service } from 'egg';
import ResponseModel from './../model/responseModel';
import uuidv1 = require('uuid/v1');
import ResponseListModel from '../model/responseListModel';
import {
  IQueryListCommonParams,
  ESysErrorCode,
} from '../abstract/interface/common';
import {
  IApplicationUserModel,
  UserInfoEntity,
  IUser,
} from '../model/user';
import loginAop from '../aop/loginAop';
import { UserRoleEnum } from "@/constants/enum.types";
export interface IAddUserParams {
  name: string;
  password: string;
  role: UserRoleEnum;
  email?: string;
  phone?: string;
}

export interface IQueryUserListParams {
  searchTxt: string;
  role: string;
}

export interface IEditUserParams {
  uuid: string;
  name?: string;
  email?: string;
  phone?: string;
  role?: string;
  jToken?: string;
}

export interface IDeleteUserParams {
  uuid: string;
}

export interface IQueryUserParams {
  uuid?: string;
  name?: string;
  email?: string;
}

export interface ILoginParams {
  name?: string;
  email?: string;
  password: string;
  grant_type?: 'authorization';
  gitlab_open_id?: string;
}

export interface IUpdateUserBaseInfoParams {
  uuid: string;
  name?: string;
  nickName?: string;
  email?: string;
  phone?: string;
  sex?: string;
  belongCenter?: string;
  gitlab_open_id?: string;
  belongDepartment?: string;
}

export interface IEditUserPwdParams {
  oldPwd: string;
  newPwd: string;
}

interface IEditUserPwdServiceParams extends IEditUserPwdParams {
  uuid: string;
}

export interface IEditUserEmailParams {
  oldEmail: string;
  newEmail: string;
}

interface IEditUserEmailServiceParams extends IEditUserEmailParams {
  uuid: string;
}

export default class UserService extends Service {
  /**
   * 添加用户
   */
  public async addUser(params: IAddUserParams) {
    const responseModel = new ResponseModel();
    try {
      const queryResult = await this.ctx.model.User.findOne({
        name: params.name,
      });
      if (queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '用户已注册，请更换用户名';
        responseModel.success = true;
        return responseModel;
      }
      if (params.email) {
        const qResult = await this.ctx.model.User.findOne({
          email: params.email,
        });
        if (qResult) {
          responseModel.code = ESysErrorCode.WARNING;
          responseModel.message = '邮箱已被注册，请更换新邮箱';
          responseModel.success = true;
          return responseModel;
        }
      }
      // 根据时间戳生成uuid
      const uuid = uuidv1();
      // 使用uuid作为hmac哈希算法的秘钥加密用户密码
      const cryptoPwd = this.app.cryptoTextByHmac(uuid,params.password);
      const pwdStrength = this.app.judgePwdStrength(params.password);
      const insertResult = await this.ctx.model.User.create({
        ...params,
        roleNo: UserRoleEnum[params.role],
        uuid,
        password: cryptoPwd,
        pwdStrength,
      } as any as IUser);
      if (insertResult) {
        responseModel.code = ESysErrorCode.SUCCESS;
        responseModel.data = insertResult;
        responseModel.message = '注册成功';
        responseModel.success = true;
      } else {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '注册失败';
        responseModel.success = false;
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 修改用户
   */
  public async editUser(params: IEditUserParams) {
    const responseModel = new ResponseModel<IApplicationUserModel>();
    let queryResult: IApplicationUserModel | null = null;
    try {
      queryResult = await this.ctx.model.User.findOne({
        uuid: params.uuid,
      });
      if (!queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '未找到此用户';
        responseModel.success = false;
      } else {
        if (params.name) {
          const queryResultArr = await this.ctx.model.User.find({
            name: params.name,
            uuid: { $ne: params.uuid },
          });
          if (queryResultArr.length) {
            responseModel.code = ESysErrorCode.WARNING;
            responseModel.message = '用户名已被注册，请更换用户名';
            responseModel.success = false;
            return {
              ...responseModel,
              prevData: queryResult || null,
            };
          }
        }
        const roleNo = params.role || queryResult.role;
        const insertResult = await this.ctx.model.User.updateOne(
          {
            uuid: params.uuid,
          },
          this.ctx.app.generateInsertObj(params,{
            role: () => ({
              roleNo: UserRoleEnum[roleNo],
              role: params.role,
            }),
          }),
        );
        if (insertResult.nModified) {
          responseModel.code = ESysErrorCode.SUCCESS;
          // @ts-ignore
          responseModel.data = { ...queryResult.toObject(),...params };
          responseModel.message = '修改成功';
          responseModel.success = true;
        } else {
          responseModel.code = ESysErrorCode.WARNING;
          responseModel.message = '修改失败';
          responseModel.success = false;
        }
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return {
      ...responseModel,
      prevData: queryResult || null,
    };
  }
  /**
   * 删除用户
   */
  public async deleteUser(params: IDeleteUserParams) {
    const responseModel = new ResponseModel<IApplicationUserModel>();
    try {
      const queryResult = await this.ctx.model.User.findOne({
        uuid: params.uuid,
      });
      if (!queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '未找到此用户';
        responseModel.success = false;
        return responseModel;
      }
      const deleteResult = await this.ctx.model.User.deleteOne({
        uuid: params.uuid,
      });
      if (deleteResult.deletedCount) {
        responseModel.code = ESysErrorCode.SUCCESS;
        responseModel.data = queryResult;
        responseModel.message = '删除成功';
        responseModel.success = true;
      } else {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '删除失败';
        responseModel.success = false;
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 查询用户列表
   */
  public async queryUserList(
    params: Partial<IQueryUserListParams>,
    pageOptions: IQueryListCommonParams<number>,
  ) {
    const responseListModel = new ResponseListModel();
    const { page,pageSize } = pageOptions;
    /** 不区分大小写 */
    const reg = new RegExp(params.searchTxt || '','i');
    try {
      const queryResult = await this.ctx.model.User.find(
        {
          $or: [
            {
              name: { $regex: reg },
            },
            {
              email: { $regex: reg },
            },
            {
              phone: { $regex: reg },
            },
          ],
        },
        {
          password: 0,
        },
        {
          sort: {
            createTime: 'desc',
          },
          limit: pageSize,
          skip: (page - 1) * pageSize,
        },
      );
      const userTotalNumber = await this.ctx.model.User.countDocuments({});
      responseListModel.code = ESysErrorCode.SUCCESS;
      responseListModel.message = '查询成功';
      responseListModel.success = true;
      responseListModel.data = {
        page,
        pageSize,
        list: queryResult || [],
        total: userTotalNumber || 0,
      };
    } catch (error) {
      this.logger.error(error);
      responseListModel.code = ESysErrorCode.CRASH;
      responseListModel.message = '系统异常';
      responseListModel.success = false;
    }
    return responseListModel;
  }
  /**
   * 根据id查询单个用户
   */
  public async queryUserById(params: { id: string }) {
    const responseModel = new ResponseModel();
    try {
      const queryResult = await this.ctx.model.User.findById(params.id);
      if (!queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '未找到此用户';
        responseModel.success = false;
        return responseModel;
      }
      responseModel.code = ESysErrorCode.SUCCESS;
      responseModel.message = '查询成功';
      responseModel.success = true;
      responseModel.data = queryResult;
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 查询单个用户
   */
  public async queryUser(params: IQueryUserParams) {
    const responseModel = new ResponseModel();
    try {
      if (JSON.stringify(params) === '{}') {
        responseModel.code = ESysErrorCode.CRASH;
        responseModel.message = '请输入查询参数';
        responseModel.success = false;
        return responseModel;
      }
      const queryResult = await this.ctx.model.User.findOne({
        ...params,
      });
      if (!queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '未找到此用户';
        responseModel.success = false;
        return responseModel;
      }
      responseModel.code = ESysErrorCode.SUCCESS;
      responseModel.message = '查询成功';
      responseModel.success = true;
      responseModel.data = queryResult;
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 登陆用户
   */
  @loginAop
  public async login(params: ILoginParams) {
    const responseModel = new ResponseModel<IApplicationUserModel>();
    try {
      if (!params.email && !params.name) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '必须传入用户名或者邮箱';
        responseModel.success = false;
        return responseModel;
      }
      const queryResult = await this.ctx.model.User.findOne({
        $or: [
          {
            name: params.name,
          },
          {
            email: params.email,
          },
        ],
      });
      if (!queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '账号不存在';
        responseModel.success = false;
        return responseModel;
      }
      if (params.grant_type !== 'authorization') {
        if (
          queryResult.password !==
          this.app.cryptoTextByHmac(queryResult.uuid,params.password)
        ) {
          responseModel.code = ESysErrorCode.WARNING;
          responseModel.message = '账号或密码错误';
          responseModel.success = false;
          return responseModel;
        }
      }
      const expiresTime = '30d';
      const userInfo: UserInfoEntity = {
        id: queryResult._id,
        uuid: queryResult.uuid,
        name: queryResult.name,
        email: queryResult.email!,
        phone: queryResult.phone!,
        role: queryResult.role,
        roleNo: UserRoleEnum[queryResult.role],
      };
      const token = this.app.jwt.sign(
        {
          userInfo,
        },
        this.config.jwt.secret,
        {
          expiresIn: expiresTime,
        },
      );
      const lastLoginTime = new Date();
      const responseObj = Object.assign(queryResult.toObject(),{
        password: '',
        token,
        expiresTime,
        lastLoginTime,
      });
      responseModel.code = ESysErrorCode.SUCCESS;
      responseModel.message = '登录成功';
      // @ts-ignore
      responseModel.data = responseObj;
      responseModel.success = true;
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 重置指定用户密码成为默认密码
   */
  public async resetDefaultPwd(params: { uuid: string }) {
    const responseModel = new ResponseModel<IApplicationUserModel>();
    try {
      // 使用uuid作为hmac哈希算法的秘钥加密用户密码
      const cryptoPwd = this.app.cryptoTextByHmac(params.uuid,'123456');
      const updateResult = await this.ctx.model.User.findOneAndUpdate(
        {
          uuid: params.uuid,
        },
        {
          password: cryptoPwd,
        },
      );
      if (updateResult) {
        responseModel.code = ESysErrorCode.SUCCESS;
        responseModel.data = updateResult;
        responseModel.message = '密码重置成功，新密码为123456';
        responseModel.success = true;
      } else {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '未找到此用户，密码重置失败';
        responseModel.success = false;
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 修改指定用户的密码
   */
  public async editUserPwdService(params: IEditUserPwdServiceParams) {
    const responseModel = new ResponseModel();
    try {
      const queryResult = await this.ctx.model.User.findOne({
        uuid: params.uuid,
      });
      if (!queryResult) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '未找到此用户';
        responseModel.success = false;
        return responseModel;
      }
      const oldPwd = queryResult.password;
      const cryptoOldPwd = this.app.cryptoTextByHmac(
        params.uuid,
        params.oldPwd,
      );
      if (oldPwd !== cryptoOldPwd) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '旧密码不正确';
        (responseModel.data = {
          errField: ['oldPwd'],
        }),
          (responseModel.success = false);
        return responseModel;
      }
      if (params.oldPwd === params.newPwd) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '新密码与旧密码重复';
        (responseModel.data = {
          errField: ['newPwd'],
        }),
          (responseModel.success = false);
        return responseModel;
      }
      const cryptoNewPwd = this.app.cryptoTextByHmac(
        params.uuid,
        params.newPwd,
      );
      const pwdStrength = this.app.judgePwdStrength(params.newPwd);
      const updateResult = await this.ctx.model.User.updateOne(
        {
          uuid: params.uuid,
        },
        {
          password: cryptoNewPwd,
          pwdStrength,
        },
      );
      if (updateResult.nModified) {
        responseModel.code = ESysErrorCode.SUCCESS;
        responseModel.message = '修改密码成功';
        responseModel.success = true;
        responseModel.data = null;
      } else {
        responseModel.code = ESysErrorCode.ERROR;
        responseModel.message = '修改密码出错，请稍后重试';
        responseModel.success = false;
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /**
   * 修改指定用户的邮箱
   */
  public async editUserEmailService(params: IEditUserEmailServiceParams) {
    const responseModel = new ResponseModel();
    try {
      const queryResult = await this.queryUser({ uuid: params.uuid });
      if (!queryResult.success) {
        return queryResult;
      }
      const queryOldEmail = (queryResult.data as IApplicationUserModel).email;
      const oldEmail = params.oldEmail;
      const newEmail = params.newEmail;
      if (queryOldEmail !== oldEmail) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '旧邮箱不正确';
        responseModel.data = {
          errField: ['oldEmail'],
        };
        responseModel.success = false;
        return responseModel;
      }
      if (oldEmail === newEmail) {
        responseModel.code = ESysErrorCode.WARNING;
        responseModel.message = '新邮箱与旧邮箱重复';
        responseModel.data = {
          errField: ['newEmail'],
        };
        responseModel.success = false;
        return responseModel;
      }
      const updateResult = await this.ctx.model.User.updateOne({
        uuid: params.uuid,
      },{
        email: newEmail,
      });
      if (updateResult.nModified) {
        responseModel.code = ESysErrorCode.SUCCESS;
        responseModel.message = '修改邮箱成功';
        responseModel.success = true;
        responseModel.data = null;
      } else {
        responseModel.code = ESysErrorCode.ERROR;
        responseModel.message = '修改邮箱出错，请稍后重试';
        responseModel.success = false;
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }
  /*** 更新指定用户的基本信息 */
  public async updateUserBaseInfo(params: IUpdateUserBaseInfoParams) {
    const responseModel = new ResponseModel();
    try {
      const updateRes = await this.ctx.model.User.findOneAndUpdate(
        { uuid: params.uuid },
        {
          name: params.name,
          nickName: params.nickName,
          sex: params.sex,
          email: params.email,
          phone: params.phone,
          belongCenter: params.belongCenter,
          gitlab_open_id: params.gitlab_open_id,
          belongDepartment: params.belongDepartment,
        },
      );
      if (updateRes) {
        responseModel.code = ESysErrorCode.SUCCESS;
        responseModel.message = '修改成功';
        responseModel.data = null;
        responseModel.success = true;
      } else {
        responseModel.code = ESysErrorCode.ERROR;
        responseModel.message = '修改失败';
        responseModel.data = null;
        responseModel.success = true;
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel;
  }

  private async editUserGitlabOpenId(params: {
    gitlab_open_id: string;
    uuid: string;
  }) {
    try {

      const updateResult = await this.ctx.model.User.updateOne({
        uuid: params.uuid,
      },{
        gitlab_open_id: params.gitlab_open_id,
      });
      if (updateResult.nModified) {
        return true
      } else {
        return false
      }
    } catch (error) {
      this.logger.error(error);
      return false
    }
  }
  /**
   * 授权登录
   * @param params 
   * @returns 
   */
  public async oauthLogin(params: ILoginParams) {
    let responseModel = new ResponseModel<IApplicationUserModel>();
    try {
      const query_result = await this.ctx.model.User.findOne({
        $or: [
          {
            name: params.name,
          },
          {
            email: params.email,
          },
        ],
      });
      if (!query_result) {
        const role = UserRoleEnum[UserRoleEnum.developer]
        /** 账户不存在，先根据授权账户信息进行注册，注册完成后生成初始密码,然后以初始密码进行登录 */
        const regist_result = await this.addUser({
          name: params.name || '',
          password: 'a123456',
          //@ts-ignore
          role,
          gitlab_open_id: params.gitlab_open_id,
          email: params.email || ''
        })
        if (regist_result.success) {
          responseModel = await this.login({
            name: params.name,
            email: params.email,
            password: 'a123456',
          })
        }
      } else {
        if (!query_result.gitlab_open_id) {
          await this.editUserGitlabOpenId({
            uuid: query_result.uuid,
            gitlab_open_id: params.gitlab_open_id as string
          })
        }
        /** 如果已经存在，则直接不需要密码进行登录 */
        responseModel = await this.login({
          name: params.name,
          email: params.email,
          password: '',
          grant_type: 'authorization'
        })
      }
    } catch (error) {
      this.logger.error(error);
      responseModel.code = ESysErrorCode.CRASH;
      responseModel.message = '系统异常';
      responseModel.success = false;
    }
    return responseModel
  }
}
